package com.example.demoannotation.aspect;

import com.example.demoannotation.annotation.LoginUser;
import com.example.demoannotation.bean.LoginUserBean;
import com.example.demoannotation.service.HostHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;


/**
 *
 *
 *
 */
/* Token转化LoginUserBean
 方法supportsParameter很好理解，返回值是boolean类型，它的作用是判断Controller层中的参数，
 是否满足条件，满足条件则执行resolveArgument方法，不满足则跳过。

 而resolveArgument方法呢，它只有在supportsParameter方法返回true的情况下才会被调用。
 用于处理一些业务，将返回值赋值给Controller层中的这个参数。

 因此呢，我们可以将HandlerMethodArgumentResolver理解为是一个参数解析器，
 我们可以通过写一个类实现HandlerMethodArgumentResolver接口来实现对Controller层中方法参数的修改。
 */
@Slf4j
public class TokenArgumentResolver implements HandlerMethodArgumentResolver {


    //请求头
    private static final String tokenHeader = "Authorization";

    //请求令牌中特定的字符序列
    private static final String tokenHead = "Bearer";

    //redis路由键
    private static final String redisTokenKey = "HE_TOKEN:";

    @Resource
    private HostHolder hostHolder;


    /**
     * 入参筛选
     *
     * @param methodParameter 参数集合
     * @return 格式化后的参数
     */
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        log.info("support :{}",methodParameter.hasParameterAnnotation(LoginUser.class));
        return methodParameter.hasParameterAnnotation(LoginUser.class)
                && methodParameter.getParameterType().equals(LoginUserBean.class);
    }

    /**
     * @param methodParameter       入参集合
     * @param modelAndViewContainer model 和 view
     * @param nativeWebRequest      web相关
     * @param webDataBinderFactory  入参解析
     * @return 包装对象
     */
    @Override
    public Object resolveArgument(MethodParameter methodParameter,
                                  ModelAndViewContainer modelAndViewContainer,
                                  NativeWebRequest nativeWebRequest,
                                  WebDataBinderFactory webDataBinderFactory) {

        LoginUser loginUser = methodParameter.getParameterAnnotation(LoginUser.class);
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);

        //1.从请求头部获取授权令牌
        final String authHead = request.getHeader(tokenHeader);
        log.info("controller request header:[{}]",authHead);
        String authToken = authHead.substring(tokenHead.length()+1);

        LoginUserBean user = new LoginUserBean();
        // 从token获取
        if (loginUser.isFull()){
            //2.1 判断redis中是否存在相应的token信息

            user.setName("token-yanjl");
            user.setPassword("123456");
            log.info("brear token value:[{}],auth user info:{}",authToken, user);
        }else {
            // 否则从Thread local 获取
            user = hostHolder.getUser();
            log.info("Thread local user info:{}", user);
        }

        return user;
    }
}
